package com.mhc.haval.service.impl;

import com.mhc.haval.bo.EditPasswordBO;
import com.mhc.haval.bo.StaffBO;
import com.mhc.haval.constant.*;
import com.mhc.haval.dal.mapper.ext.RoleExtMapper;
import com.mhc.haval.dal.mapper.ext.StaffAreaExtMapper;
import com.mhc.haval.dal.mapper.ext.StaffExtMapper;
import com.mhc.haval.dal.mapper.ext.StaffRoleExtMapper;
import com.mhc.haval.dal.model.*;
import com.mhc.haval.dal.query.DepartmentQuery;
import com.mhc.haval.dal.query.StaffAreaQuery;
import com.mhc.haval.dal.query.StaffQuery;
import com.mhc.haval.dal.query.StaffRoleQuery;
import com.mhc.haval.exception.HavalCommonException;
import com.mhc.haval.manager.DepartmentManager;
import com.mhc.haval.manager.StaffAreaManager;
import com.mhc.haval.manager.StaffManager;
import com.mhc.haval.manager.StaffRoleManager;
import com.mhc.haval.service.StaffService;
import com.subaru.common.query.PageResult;
import com.subaru.common.util.BeanCopierUtil;
import com.subaru.common.util.MD5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by HMJ on 2017/8/17.
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class StaffServiceImpl implements StaffService {

    public static final String DEFAULTPW = "Hello!@#";

    @Autowired
    private StaffManager staffManager;
    @Autowired
    private StaffRoleManager staffRoleManager;
    @Autowired
    private StaffExtMapper staffExtMapper;
    @Autowired
    private RoleExtMapper roleExtMapper;
    @Autowired
    private StaffAreaManager staffAreaManager;
    @Autowired
    private StaffRoleExtMapper staffRoleExtMapper;
    @Autowired
    private StaffAreaExtMapper staffAreaExtMapper;
    @Autowired
    DepartmentManager departmentManager;

    /**
     * 查询员工列表
     *
     * @param staffBO 员工查询条件实体
     * @return
     * @throws Exception
     */
    @Override
    public PageResult<StaffBO> queryByStaffList(StaffBO staffBO) throws HavalCommonException {
        log.info("开始查询系统用户管理列表...");
        Map<String, Object> paramMap = new HashMap<>(64);
        paramMap.put("keyword", staffBO.getKeyword());             //关键字
        paramMap.put("deptId", staffBO.getDeptId());               //部门ID
        paramMap.put("pageSize", staffBO.getPageSize());           //每页大小
        paramMap.put("status", StaffStatusEnum.DELETED.getCode()); //已删除
        /**计算pageOffset**/
        StaffQuery query = new StaffQuery();
        query.setPageNo(staffBO.getPageNo());
        query.setPageSize(staffBO.getPageSize());
        paramMap.put("pageOffset", query.getPageOffset());           //开始查询位
        /**查询系统用户列表**/
        List<StaffBO> staffList = staffExtMapper.queryByStaffList(paramMap);
        if (!staffList.isEmpty()) {
            for (StaffBO staffbo : staffList) {
                List<RoleDO> list = roleExtMapper.queryByUserid(staffbo.getStaffId());
                staffbo.setRoleArray(rolesToStr(list));
            }
        }
        /**查询系统用户总条数**/
        int count = staffExtMapper.countByStaffList(paramMap);
        log.info("系统用户条数为：" + count + "条");
        PageResult<StaffBO> result = new PageResult<>();
        result.setPageNo(staffBO.getPageNo());
        result.setPageSize(staffBO.getPageSize());
        result.setTotalCount(count);
        result.setResult(staffList);
        return result;
    }

    /**
     * 按部门查询员工列表
     * @param deptId 部门ID
     * @return 员工列表
     **/
    @Override
    public List<StaffDO> getStaffsByDept(Long deptId) {
        StaffQuery query = new StaffQuery();
        query.createCriteria().andDeptIdEqualTo(deptId).andStatusEqualTo(StaffStatusEnum.NORMAL.getCode());

        return staffManager.selectByQuery(query);
    }

    /**
     * 角色列表转成字符串
     *
     * @param list
     * @return
     */
    private List<Map> rolesToStr(List<RoleDO> list) throws HavalCommonException{
        List<Map> arrylist = new ArrayList<>();
        if(list!=null && !list.isEmpty()){
            /**循环遍历list取出角色ID和角色名称**/
            for (int i = 0; i < list.size(); i++) {
                RoleDO role = list.get(i);
                Map<String, Object> paramMap = new HashMap<>(64);
                paramMap.put("roleId", role.getRoleId());
                paramMap.put("roleName", role.getRoleName());
                arrylist.add(paramMap);
            }
        }
        return arrylist;
    }

    /**
     * 新增员工信息
     *
     * @param staffBO   员工实体
     * @param roleArray 员工角色
     * @return
     */
    @Override
    public Boolean addStaffInfo(StaffBO staffBO, String[] roleArray) throws HavalCommonException {
        log.info("开始新增员工信息...");
        StaffQuery staffQuery = new StaffQuery();
        StaffDO staffDO = new StaffDO();
        StaffRoleDO staffRoleDO = new StaffRoleDO();
        StaffAreaDO staffAreaDO = new StaffAreaDO();
        StaffQuery.Criteria criteria = staffQuery.createCriteria();
        /**根据前端传来的参数查询账户是否存在**/
        log.info("正在校验数据准确性，请稍后...");
        if (StringUtils.isNotBlank(staffBO.getPhone())) {
            criteria.andPhoneEqualTo(staffBO.getPhone());
            List<StaffDO> data = staffManager.selectByQuery(staffQuery);
            if (!data.isEmpty()) {
                /**data.size() > 0  账户存在**/
                log.info("当前用户已存在！请重新确认...");
                throw new HavalCommonException(MsgCodeEnum.USER_EXISTS);  //账号已被注册
            } else {
                /**data.size()< 0，新增员工**/
                log.info("数据校验完成，正在新增新用户...");
                String[] deptArry = staffBO.getSelectedDept();
                if (deptArry.length > 0) {
                    /**解析部门列表，取部门ID**/
                    Long deptId = Long.parseLong(deptArry[deptArry.length - 1]);
                    staffBO.setDeptId(deptId);
                    /**BO转DO进行存储**/
                    log.info("开始新增员工信息...");
                    BeanCopierUtil.copy(staffBO, staffDO);
                    staffDO.setStatus(StaffStatusEnum.NORMAL.getCode());
                    staffDO.setPassword(MD5Util.stringMD5(DEFAULTPW));   /**密码加密(MD5加密)**/
                    staffManager.insertSelective(staffDO);
                    log.info("员工信息新增完成");
                    /**新增员工角色关系**/
                    log.info("开始关联员工角色...");
                    staffRoleDO.setStaffId(staffDO.getStaffId());
                    if (roleArray.length > 0) {
                        for (int i = 0; i < roleArray.length; i++) {
                            staffRoleDO.setRoleId(Long.parseLong(roleArray[i]));
                            staffRoleDO.setIsDeleted(IsDeletedEnum.NORMAL.getCode());
                            staffRoleManager.insertSelective(staffRoleDO);
                        }
                    }
                    log.info("员工角色关联完成...");
                    /**如果存在--新增员工角色银行关系**/
                    if (staffBO.getBankId() != null) {
                        log.info("该员工属于驻点人员，正在分配银行...");
                        staffAreaDO.setStaffId(staffDO.getStaffId());
                        staffAreaDO.setAreaType(AreaEnum.BANK.getCode());
                        staffAreaDO.setAreaId(staffBO.getBankId());
                        staffAreaDO.setIsDeleted(IsDeletedEnum.NORMAL.getCode());
                        staffAreaManager.insertSelective(staffAreaDO);
                        log.info("分配银行完成");
                    }
                    return true;
                }
                throw new HavalCommonException(MsgCodeEnum.DEPT_EMPTRY);  //所属部门为空
            }
        }
        throw new HavalCommonException(MsgCodeEnum.EMPTY_USER);  //获取用户为空
    }


    /**
     * 修改员工信息
     *
     * @param staffBO   员工实体
     * @param roleArray 员工角色
     * @return
     */
    @Override
    public Boolean editStaffInfo(StaffBO staffBO, String[] roleArray) throws HavalCommonException {
        /**2、修改员工信息**/
        StaffBO staffInfo = this.checkStaffExist(staffBO);
        StaffDO staffDO = new StaffDO();
        StaffRoleQuery query = new StaffRoleQuery();
        query.createCriteria().andStaffIdEqualTo(staffBO.getStaffId());   //员工编号
        if (roleArray.length > 0) {
            log.info("当前存在角色关联...");
            List<StaffRoleDO> lists = new ArrayList<>();
            /**解析部门列表，取部门ID**/
            String[] deptArry = staffBO.getSelectedDept();
            if(deptArry.length>0){
                log.info("正在修改用户基本信息...");
                Long deptId = Long.parseLong(deptArry[deptArry.length - 1]);
                staffInfo.setDeptId(deptId);
                BeanCopierUtil.copy(staffInfo, staffDO);
                /**修改用户信息**/
                staffManager.updateByPrimaryKeySelective(staffDO);
                log.info("修改用户基本信息完成...");
                /**修改用户-角色关联表**/
                log.info("正在修改用户角色关联信息...");
                for (int i = 0; i < roleArray.length; i++) {
                    StaffRoleDO staffRoleDO = new StaffRoleDO();
                    staffRoleExtMapper.deleteByStaffId(staffBO.getStaffId());
                    staffRoleDO.setStaffId(staffBO.getStaffId());
                    staffRoleDO.setRoleId(Long.parseLong(roleArray[i]));
                    staffRoleDO.setIsDeleted(IsDeletedEnum.NORMAL.getCode());
                    lists.add(staffRoleDO);
                }
                staffRoleExtMapper.batchAddStaffRoleRel(lists);
                log.info("修改用户角色关联信息完成...");
                /**如果是银行驻点角色修改银行**/
                this.updateArea(staffBO);
            }else{
                throw new HavalCommonException(MsgCodeEnum.DEPT_EMPTRY);  //所属部门为空
            }
        } else {
            log.info("当前不存在角色关联...");
            log.info("正在删除角色以及银行关联...");
            staffRoleManager.deleteByQuery(query);
            /**无角色条件下，把所属的银行删除**/
            StaffAreaQuery staffAreaQuery = new StaffAreaQuery();
            staffAreaQuery.createCriteria().andStaffIdEqualTo(staffBO.getStaffId())
                    .andAreaTypeEqualTo(AreaEnum.BANK.getCode());   //根据员工编号、区域类型删除对应的银行
            staffAreaManager.deleteByQuery(staffAreaQuery);
            log.info("删除完成...");
        }
        return true;
    }


    /**
     * 查看员工详情信息
     *
     * @param staffId
     * @return
     */
    @Override
    public StaffBO queryStaffInfoByStaffId(Long staffId) throws HavalCommonException {
        log.info("开始查询员工详情...");
        /**组装查询信息**/
        Map<String, Object> paramMap = new HashMap<>(64);
        paramMap.put("staffId", staffId);                //员工ID
        paramMap.put("status", StaffStatusEnum.DELETED.getCode()); //已删除
        /**查询员工详情**/
        List<StaffBO> dataList = staffExtMapper.queryByStaffList(paramMap);
        StaffBO staffBO = dataList.get(0);
        List<RoleDO> list = roleExtMapper.queryByUserid(staffBO.getStaffId());
        staffBO.setRoleArray(rolesToStr(list));
        Map<String, Object> staffAreamMap = new HashMap<>(64);
        staffAreamMap.put("staffId", staffId);
        staffAreamMap.put("areaType", AreaEnum.BANK.getCode());
        StaffAreaDO staffAreaList = staffAreaExtMapper.selectByStaffArea(staffAreamMap);
        if (staffAreaList != null) {
            staffBO.setBankId(staffAreaList.getAreaId());
        }
        Long deptId = staffBO.getDeptId();
        TreeMap<Integer, Object> deptStructure = new TreeMap<>();
        for (int i=0;deptId!=null;i++) {
            //查询当前部门的详情
            DepartmentQuery thisDepartmentQuery = new DepartmentQuery();
            thisDepartmentQuery.createCriteria().andDeptIdEqualTo(deptId);
            List<DepartmentDO>  departList = departmentManager.selectByQuery(thisDepartmentQuery);
            if(!departList.isEmpty()){
                DepartmentDO departmentDO = departList.get(0);
                //放入部门结构map中
                deptStructure.put(i, departmentDO);
                //继续递归往上查
                deptId = departmentDO.getParentDeptId();
            }else {
                deptId = null;
            }
        }
        staffBO.setDeptStructure(deptStructure.descendingMap());
        return staffBO;
    }


    /**
     * 修改密码
     * @param editPasswordBO 修改密码实体
     * @return
     */
    @Override
    public Boolean updateByPassword(EditPasswordBO editPasswordBO) throws HavalCommonException{
        log.info("开始修改密码...");
        Long staffId = editPasswordBO.getStaffId();     //员工编号
        String oldPassword = editPasswordBO.getOldPassword();  //旧密码
        String newPassword = editPasswordBO.getNewPassword();  //新密码
        /**根据员工ID查询员工信息**/
        if(oldPassword!=null && newPassword!=null){
            StaffDO staffInfo = staffManager.selectByPrimaryKey(staffId);
            String staffPassword = staffInfo.getPassword();   //数据库的密码  加密的
            String md5OldPassword = MD5Util.stringMD5(oldPassword);  //旧密码加密后
            /**验证页面密码与原密码是否相同**/
            log.info("正在验证密码是否相同...");
            if (md5OldPassword.endsWith(staffPassword)) {
                /**旧密码加密后与数据库相同**/
                log.info("密码相同，开始修改密码...");
                String md5NewPassword = MD5Util.stringMD5(newPassword);  //页面上新密码加密
                if(md5NewPassword.endsWith(md5OldPassword)){
                    throw new HavalCommonException(MsgCodeEnum.PASSWORD_ALIKE);  //新密码与原密码相同
                }else {
                    StaffDO record = new StaffDO();
                    record.setStaffId(staffId);
                    record.setPassword(md5NewPassword);
                    staffManager.updateByPrimaryKeySelective(record);
                    log.info("修改完成...");
                    return true;
                }
            }
            /**原密码与数据库不同**/
            throw new HavalCommonException(MsgCodeEnum.PASSWORD_ERROR);  //密码验证失败
        }
        throw new HavalCommonException(MsgCodeEnum.PARAM_ERROR);  //参数错误
    }

    /**
     * 修改区域信息
     **/
    public void updateArea(StaffBO staffBO) throws HavalCommonException{
        StaffAreaDO record = new StaffAreaDO();
        StaffAreaQuery query = new StaffAreaQuery();
        StaffAreaQuery.Criteria criteria = query.createCriteria();
        criteria.andStaffIdEqualTo(staffBO.getStaffId())
                .andIsDeletedEqualTo(IsDeletedEnum.NORMAL.getCode())
                .andAreaTypeEqualTo(AreaEnum.BANK.getCode());
        /**根据员工编号查询当前员工是否存在驻点银行**/
        List<StaffAreaDO> list = staffAreaManager.selectByQuery(query);
        /**修改员工工作区域表状态**/
        Map<String, Object> paramMap = new HashMap<>(64);
        paramMap.put("staffId", staffBO.getStaffId());
        paramMap.put("isDeleted", IsDeletedEnum.DELETED.getCode());
        paramMap.put("areaType", AreaEnum.BANK.getCode());
        if (!list.isEmpty()) {
            /**存在员工和银行关系**/
            Long areaId = list.get(0).getAreaId();
            if (staffBO.getBankId() == null) {
                /**当修改参数不含银行时，把当前员工所属的银行信息修改成"已删除"**/
                paramMap.put("areaId", areaId);
                staffAreaExtMapper.updateStaffAreaByType(paramMap);
            } else {
                /**当修改前的银行ID不等于修改参数的银行ID时**/
                if (!areaId.equals(staffBO.getBankId())) {
                    /**先将之前的银行信息置为”已删除",然后再新增信息**/
                    paramMap.put("areaId", areaId);
                    staffAreaExtMapper.updateStaffAreaByType(paramMap);
                    record.setStaffId(staffBO.getStaffId());
                    record.setAreaType(AreaEnum.BANK.getCode());
                    record.setAreaId(staffBO.getBankId());
                    record.setIsDeleted(IsDeletedEnum.NORMAL.getCode());
                    staffAreaManager.insertSelective(record);
                }
            }
        } else {
            /**不存在员工和银行关系,但是修改参数包含银行，则新增**/
            if (staffBO.getBankId() != null) {
                record.setStaffId(staffBO.getStaffId());
                record.setAreaType(AreaEnum.BANK.getCode());
                record.setAreaId(staffBO.getBankId());
                record.setIsDeleted(IsDeletedEnum.NORMAL.getCode());
                staffAreaManager.insertSelective(record);
            }
        }
        log.info("修改员工银行信息完成");
    }


    /**
     * 停用/启用员工
     *
     * @param staffBO
     * @return
     * @throws Exception
     */
    @Override
    public Boolean updateByStaffStatus(StaffBO staffBO) throws HavalCommonException {
        log.info("开始验证员工目前状态....");
        StaffDO record = new StaffDO();
        StaffQuery query = new StaffQuery();
        StaffQuery.Criteria criteria = query.createCriteria();
        criteria.andStaffIdEqualTo(staffBO.getStaffId());
        int status = staffBO.getStatus();      //获取用户状态
        if (status == StaffStatusEnum.NORMAL.getCode()) {
            /**当前状态为：正常**/
            log.info("当前员工目前状态为：" + StaffStatusEnum.NORMAL.getName());
            record.setStatus(StaffStatusEnum.BLOCKUP.getCode());
        }
        if (StaffStatusEnum.BLOCKUP.getCode().equals(staffBO.getStatus())) {
            /**当前状态为：停用**/
            log.info("当前员工目前状态为：" + StaffStatusEnum.BLOCKUP.getName());
            record.setStatus(StaffStatusEnum.NORMAL.getCode());
        }
        int i = staffManager.updateByQuerySelective(record, query);
        if (i > 0) {
            log.info("当前员工状态已修改完成");
            return true;
        }
        throw new HavalCommonException(MsgCodeEnum.UPDATE_FAIL);
    }

    /**
     * 重置密码
     *
     * @param staffId
     * @return
     * @throws Exception
     */
    @Override
    public Boolean resetPassword(Long staffId) throws HavalCommonException {
        log.info("开始重置密码...");
        StaffDO record = new StaffDO();
        record.setPassword(MD5Util.stringMD5(DEFAULTPW));   /**默认密码"123456",密码加密(MD5加密)**/
        record.setStaffId(staffId);
        int i = staffManager.updateByPrimaryKeySelective(record);
        if (i > 0) {
            log.info("重置密码完成...");
            return true;
        }
        throw new HavalCommonException(MsgCodeEnum.UPDATE_FAIL);
    }

    /**
     * 校验提交的手机号码是否重复
     * @param staffBO
     * @return
     */
    public StaffBO  checkStaffExist(StaffBO staffBO){
        /**1、校验提交的手机号码是否重复**/
        log.info("开始修改员工信息...");
        StaffQuery staffQuery = new StaffQuery();
        staffQuery.createCriteria().andStaffIdEqualTo(staffBO.getStaffId()).andStatusNotEqualTo(IsDeletedEnum.DELETED.getCode());
        List<StaffDO> staffList = staffManager.selectByQuery(staffQuery);
        if(staffList.isEmpty()){
            throw new HavalCommonException(MsgCodeEnum.QUERY_FAIL);  //查询错误
        }
        if(staffBO.getPhone().equals(staffList.get(0).getPhone())){
            /**修改的内容和原内容相同**/
            return staffBO;
        }else {
            /**修改的内容和原内容不同**/
            log.info("正在校验手机号码是否重复...");
            StaffQuery query = new StaffQuery();
            query.createCriteria().andPhoneEqualTo(staffBO.getPhone()).andStatusNotEqualTo(IsDeletedEnum.DELETED.getCode());
            List<StaffDO> list = staffManager.selectByQuery(query);
            if(!list.isEmpty()){
                /**手机号码存在**/
                log.error("当前手机号码已存在...");
                throw new HavalCommonException(MsgCodeEnum.USER_EXISTS);  //用户存在
            }else {
                /**手机号码不存在**/
                log.error("可以修改当前手机号码...");
                return staffBO;
            }
        }

    }
}
